#!/user/bin/env python3
# -*- coding: utf-8 -*-

# Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。
# 如果函数收到的是一个可变对象（比如字典或者列表）的引用，就能修改对象的原始值－－相当于通过“传引用”来传递对象。
# 如果函数收到的是一个不可变对象（比如数字、字符或者元组）的引用，就不能直接修改原始对象－－相当于通过“传值'来传递对象


def param_test(list_1):
    list_1.append('test')

l = ['123']
param_test(l)
print(l)


def power(x, n=2):
    s = 1
    while n > 0:
        n = n - 1
        s = s * x
    return s


print(power(5, 3))
print(power(5))


def enroll(name, gender, age=20, city='California'):
    print("name : ", name)
    print("gender: ", gender)
    print("age : ", age)
    print("city ", city)


enroll('jzq', 'Freshman')
enroll('mrx', 'First grade', city='Los Angeles')


# Python函数在定义的时候，默认参数L的值就被计算出来了，即[]，因为默认参数L也是一个变量，它指向对象[]，
# 每次调用该函数，如果改变了L的内容，则下次调用时，默认参数的内容就变了，不再是函数定义时的[]了。
# 所以，定义默认参数要牢记一点：默认参数必须指向不变对象！


def add_end(l=[]):
    l.append('end')
    print(l)


add_end()
add_end()


def add_end2(l=None):
    if l is None:
        l = []
    l.append('end')
    print(l)


add_end2()
add_end2()


# 可变参数   在函数内部，参数numbers接收到的是一个tuple
def calc(*numbers):
    result = 0
    for x in numbers:
        result = result + int(x)
    return result


print(calc(1, 3, 5))


# 关键字参数允许你传入0个或任意个含参数名的参数，这些关键字参数在函数内部自动组装为一个dict
def person(name, age, **kw):
    print('name: ', name, 'age: ', age, 'other: ', kw)

person('jzq', 23, love='gxy')


# 限制关键字参数的名字，就可以用命名关键字参数


def student(name, age, *, city='jiaxing', hobby):
    print(name, age, city, hobby)

student('jzq', 22, hobby='basketball')


# 如果函数定义中已经有了一个可变参数，后面跟着的命名关键字参数就不再需要一个特殊分隔符*了
# 命名关键字参数必须传入参数名, 如果不传python解释器就把他们当成位置参数


def student2(name, age, *args, city, hobby):
    print(name, age, args, city, hobby)

student2('mrx', 23, 'gxy','hyy', 'hlt', city='jiaxing', hobby='acg')

# 参数定义的顺序必须是：必选参数、默认参数、可变参数、命名关键字参数和关键字参数


def f1(a, b, c=0, *args, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)


def f2(a, b, c=0, *, d, **kw):
    print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)

f1(1, 2)
params = (1, 2, 3, 4)
d_kw = {'name': 'jzq', 'age': 22}
f1(*params, **d_kw)

params2 = (1, 2, 3)
d_kw2 = {'d': 123, 'x': 'your name'}
f2(*params2, **d_kw2)

# 于任意函数，都可以通过类似func(*args, **kw)的形式调用它，无论它的参数是如何定义的

